#include <iostream>
#include <string>
#include <vector>
#include <cassert>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "task.hpp"

const int PROC_NUM = 5;

struct EndPoint
{
    pid_t _child_id;
    int   _write_fd;

    EndPoint(pid_t id, int fd) : _child_id(id), _write_fd(fd)
    {}
};

int ShowBoard()
{
    std::cout << "----------------------------" << std::endl;
    std::cout << "   0. log          1. sql   " << std::endl;
    std::cout << "   2. net          3. quit  " << std::endl;
    std::cout << "----------------------------" << std::endl;
    std::cout << "please select:> ";

    int command;
    std::cin >> command;
    return command;
}

void WaitCommand();

void CreateProc(std::vector<EndPoint>& end_points)
{
    std::vector<int> wfds;

    for (int i = 0; i < PROC_NUM; i++)
    {
        int pipefd[2] = {0};
        assert(pipe(pipefd) == 0);

        pid_t id = fork();
        assert(id >= 0);

        if (id == 0)
        {
            for (auto fd : wfds)
                close(fd);

            close(pipefd[1]);
            dup2(pipefd[0], 0);
            WaitCommand();
            exit(0);
        }

        close(pipefd[0]);
        end_points.push_back(EndPoint(id, pipefd[1]));

        wfds.push_back(pipefd[1]);
    }
}

void WaitCommand()
{
    while (true)
    {
        int command = 0;
        ssize_t s = read(0, &command, sizeof(command));
        if (s > 0)
        {
            Task()(command & 0xFF, (command >> 8) & 0xFF);
        }
        else 
        {
            break;
        }
    }
}

void ControlProc(std::vector<EndPoint>& end_points)
{
    int i = 0;

    while (true)
    {
        int command = ShowBoard();

        if (command < 0 || command > 2)
            break;

        command <<= 8;
        command |=  i;
        write(end_points[i]._write_fd, &command, sizeof(command)); // 前16位任务编号，后16位进程编号
        ++i;
        i %= end_points.size();
    }
}

void WaitProc(std::vector<EndPoint>& end_points)
{
    for (auto& ep : end_points)
    {
        close(ep._write_fd);
        waitpid(ep._child_id, nullptr, 0);
    }

    std::cout << "all the childprocs exited now" << std::endl;
}


int main()
{
    std::vector<EndPoint> end_points;
    CreateProc(end_points);
    ControlProc(end_points);
    WaitProc(end_points);

    return 0;
}
